package BrickControlGuide;
import java.nio.FloatBuffer;
import javax.media.opengl.GL2;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.GLUquadric;
import Builder.MainCamera;
import Common.Box3;
import Common.Matrix4;
import Common.Ray3;
import Common.Vector3f;
import LDraw.Support.MatrixMath;
public class MovementGuide extends DefaultGuideRenderer {
public MovementGuide(GLU glu) {
super.glu = glu;
}
private Vector3f[] getCylinderVertices(MainCamera camera,
Vector3f orientation) {
Vector3f[] vertices = new Vector3f[21];
final float cylinderRadius = camera.getDistanceBetweenObjectToCamera() / 40f;
final float cylinderHeight = camera.getDistanceBetweenObjectToCamera() / 20;
vertices[vertices.length - 1] = new Vector3f(0, 0, cylinderHeight);
for (int i = 0; i < vertices.length - 1; i++) {
vertices[i] = new Vector3f((float) (cylinderRadius * Math.cos(i
* Math.PI * 2 / (vertices.length - 1))),
(float) (cylinderRadius * Math.sin(i * Math.PI * 2
/ (vertices.length - 1))), 0);
}
float line_length = camera.getDistanceBetweenObjectToCamera() / 4;
Vector3f unitZVector = new Vector3f(0, 0, 1);
Vector3f rotationVector = MatrixMath.V3Cross(unitZVector,
getAxisDirectionVector());
if (rotationVector.equals(new Vector3f()))
rotationVector = new Vector3f(1, 0, 0);
Matrix4 rotationMatrix = Matrix4.getIdentityMatrix4();
if (MatrixMath.compareFloat(rotationVector.length(), 0) != 0)
rotationVector = rotationVector.scale(1 / rotationVector.length());
float angle = (float) Math.acos(unitZVector
.dot(getAxisDirectionVector())
/ (getAxisDirectionVector().length() * unitZVector.length()));
int angleInDegree = Math.round(angle / (float) (Math.PI * 2) * 360);
if (MatrixMath.compareFloat(rotationVector.length(), 0) != 0
&& Float.isNaN(angle) == false
&& MatrixMath.compareFloat(angle, 0) != 0)
rotationMatrix.rotate(-angle, rotationVector);
else if (MatrixMath.compareFloat(rotationVector.length(), 0) != 0
&& angleInDegree == 180)
rotationMatrix.rotate(angle, new Vector3f(1, 0, 0));
for (int i = 0; i < vertices.length; i++)
vertices[i] = MatrixMath.V3RotateByTransformMatrix(vertices[i],
rotationMatrix);
Vector3f endPos = getAxisDirectionVector().scale(line_length).add(
orientation);
for (int i = 0; i < vertices.length; i++)
vertices[i] = vertices[i].add(endPos);
return vertices;
}
public void drawCylinder(GL2 gl2, MainCamera camera, Vector3f orientation) {
Vector3f[] vertices = getCylinderVertices(camera, orientation);
gl2.glLoadMatrixf(camera.getModelView(), 0);
gl2.glBegin(GL2.GL_LINES); // draw using triangles
gl2.glColor3d(r, g, b);
for (int i = 0; i < vertices.length - 2; i++) {
gl2.glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
gl2.glVertex3f(vertices[i + 1].x, vertices[i + 1].y,
vertices[i + 1].z);
}
for (int i = 0; i < vertices.length - 1; i++) {
gl2.glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
gl2.glVertex3f(vertices[vertices.length - 1].x,
vertices[vertices.length - 1].y,
vertices[vertices.length - 1].z);
}
gl2.glEnd();
}
@Override
public void draw(GL2 gl2, MainCamera camera, Vector3f orientation) {
if (centerConnector != null)
orientation = getCenterPos();
float line_length = camera.getDistanceBetweenObjectToCamera() / 4;
gl2.glLoadMatrixf(camera.getModelView(), 0);
// draw guide line for x, y, z axis
gl2.glBegin(GL2.GL_LINES); // draw using triangles
gl2.glColor3d(r, g, b);
gl2.glVertex3f(orientation.getX(), orientation.getY(),
orientation.getZ());
Vector3f endPos = getAxisDirectionVector().scale(line_length).add(
orientation);
gl2.glVertex3f(endPos.x, endPos.y, endPos.z);
gl2.glEnd();
// if (orientation != null)
// return;
// draw guide arrow for x, y, z axis movement
final float cylinderRadius = camera.getDistanceBetweenObjectToCamera() / 40f;
final float cylinderHeight = camera.getDistanceBetweenObjectToCamera() / 20;
GLUquadric body = glu.gluNewQuadric();
int slices = 20;
int stacks = 10;
glu.gluQuadricTexture(body, false);
glu.gluQuadricDrawStyle(body, GLU.GLU_FILL);
glu.gluQuadricNormals(body, GLU.GLU_FLAT);
glu.gluQuadricOrientation(body, GLU.GLU_OUTSIDE);
gl2.glLoadMatrixf(camera.getModelView(), 0);
gl2.glTranslatef(endPos.x, endPos.y, endPos.z);
Vector3f unitZVector = new Vector3f(0, 0, 1);
Vector3f rotationVector = MatrixMath.V3Cross(unitZVector,
getAxisDirectionVector());
if (MatrixMath.compareFloat(rotationVector.length(), 0) != 0)
rotationVector = rotationVector.scale(1 / rotationVector.length());
if (rotationVector.equals(new Vector3f()))
rotationVector = new Vector3f(1, 0, 0);
float angle = (float) Math.acos(unitZVector
.dot(getAxisDirectionVector())
/ (getAxisDirectionVector().length() * unitZVector.length()));
int angleInDegree = Math.round(angle / (float) (Math.PI * 2) * 360);
// System.out.println("first transform: " + rotationVector + ", "
// + angleInDegree + "(" + angle + ")");
if (MatrixMath.compareFloat(rotationVector.length(), 0) != 0
&& Float.isNaN(angle) == false
&& MatrixMath.compareFloat(angle, 0) != 0)
gl2.glRotatef(angleInDegree, rotationVector.x, rotationVector.y,
rotationVector.z);
else if (MatrixMath.compareFloat(rotationVector.length(), 0) != 0
&& angleInDegree == 180)
gl2.glRotatef(angleInDegree, 1, 0, 0);
glu.gluDisk(body, 0, cylinderRadius, slices, 2);
glu.gluCylinder(body, cylinderRadius, 0, cylinderHeight, slices, stacks);
}
@Override
public boolean isHitted(MainCamera camera, Vector3f orientation,
float screenX, float screenY, FloatBuffer distance) {
if (centerConnector != null)
orientation = getCenterPos();
Ray3 ray = camera.getRay(screenX, screenY);
FloatBuffer distanceTemp = FloatBuffer.allocate(1);
Vector3f[] vertices = getCylinderVertices(camera, orientation);
boolean isHitted = false;
for (int i = 0; i < vertices.length - 1; i++) {
if (MatrixMath.V3RayIntersectsTriangle(ray, vertices[i],
vertices[(i + 1 % (vertices.length - 1))],
vertices[vertices.length - 1], distanceTemp, null)) {
if (distance != null)
if (distanceTemp.get(0) < distance.get(0))
distance.put(0, distanceTemp.get(0));
isHitted = true;
}
}
lastHittedDistance = distance.get(0);
return isHitted;
}
@Override
public float getLastHittedDistance() {
return lastHittedDistance;
}
}